#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数据库连接和管理模块
"""

from pymongo import MongoClient
from pymongo.errors import ConnectionFailure, ServerSelectionTimeoutError
from flask import current_app
import logging
from datetime import datetime
from typing import Optional, Dict, Any, List

# 全局数据库连接实例
_db_client: Optional[MongoClient] = None
_database = None

def init_database(app):
    """初始化数据库连接"""
    global _db_client, _database
    
    try:
        # 创建MongoDB客户端
        _db_client = MongoClient(
            app.config['MONGODB_URI'],
            serverSelectionTimeoutMS=5000,  # 5秒超时
            connectTimeoutMS=10000,         # 10秒连接超时
            socketTimeoutMS=0,              # 无socket超时
            maxPoolSize=10,                 # 最大连接池大小
            minPoolSize=1,                  # 最小连接池大小
        )
        
        # 获取数据库实例
        _database = _db_client[app.config['MONGODB_DB_NAME']]
        
        # 测试连接
        _db_client.admin.command('ping')
        
        app.logger.info(f"MongoDB连接成功: {app.config['MONGODB_URI']}")
        app.logger.info(f"使用数据库: {app.config['MONGODB_DB_NAME']}")
        
        return True
        
    except Exception as e:
        app.logger.error(f"MongoDB连接失败: {str(e)}")
        return False

def get_database():
    """获取数据库实例"""
    global _database
    
    if _database is None:
        from flask import current_app
        if not init_database(current_app):
            raise ConnectionError("数据库未初始化或连接失败")
    
    return _database

def get_collection(collection_name: str):
    """获取集合实例"""
    db = get_database()
    return db[collection_name]

def get_database_status() -> Dict[str, Any]:
    """获取数据库状态"""
    global _db_client, _database
    
    status = {
        'connected': False,
        'database_name': None,
        'collections': [],
        'total_documents': 0,
        'last_check': datetime.now().isoformat()
    }
    
    try:
        if _db_client is None or _database is None:
            return status
        
        # 测试连接
        _db_client.admin.command('ping')
        status['connected'] = True
        status['database_name'] = _database.name
        
        # 获取集合信息
        collections = _database.list_collection_names()
        status['collections'] = collections
        
        # 统计文档总数
        total_docs = 0
        for collection_name in collections:
            collection = _database[collection_name]
            count = collection.count_documents({})
            total_docs += count
        
        status['total_documents'] = total_docs
        
    except Exception as e:
        current_app.logger.error(f"获取数据库状态失败: {str(e)}")
        status['error'] = str(e)
    
    return status

def close_database():
    """关闭数据库连接"""
    global _db_client
    
    if _db_client:
        _db_client.close()
        _db_client = None
        current_app.logger.info("MongoDB连接已关闭")

class DatabaseManager:
    """数据库管理器"""
    
    def __init__(self, collection_name: str):
        self.collection_name = collection_name
        self._collection = None
    
    @property
    def collection(self):
        """获取集合实例"""
        if self._collection is None:
            self._collection = get_collection(self.collection_name)
        return self._collection
    
    def find_one(self, filter_dict: Dict = None, projection: Dict = None) -> Optional[Dict]:
        """查找单个文档"""
        try:
            return self.collection.find_one(filter_dict or {}, projection)
        except Exception as e:
            current_app.logger.error(f"查询单个文档失败: {str(e)}")
            return None
    
    def find(self, filter_dict: Dict = None, projection: Dict = None, 
             sort: List = None, limit: int = None, skip: int = None) -> List[Dict]:
        """查找多个文档"""
        try:
            cursor = self.collection.find(filter_dict or {}, projection)
            
            if sort:
                cursor = cursor.sort(sort)
            if skip:
                cursor = cursor.skip(skip)
            if limit:
                cursor = cursor.limit(limit)
            
            return list(cursor)
        except Exception as e:
            current_app.logger.error(f"查询多个文档失败: {str(e)}")
            return []
    
    def count_documents(self, filter_dict: Dict = None) -> int:
        """统计文档数量"""
        try:
            return self.collection.count_documents(filter_dict or {})
        except Exception as e:
            current_app.logger.error(f"统计文档失败: {str(e)}")
            return 0
    
    def insert_one(self, document: Dict) -> Optional[str]:
        """插入单个文档"""
        try:
            result = self.collection.insert_one(document)
            return str(result.inserted_id)
        except Exception as e:
            current_app.logger.error(f"插入文档失败: {str(e)}")
            return None
    
    def insert_many(self, documents: List[Dict]) -> List[str]:
        """插入多个文档"""
        try:
            result = self.collection.insert_many(documents)
            return [str(id) for id in result.inserted_ids]
        except Exception as e:
            current_app.logger.error(f"批量插入文档失败: {str(e)}")
            return []
    
    def update_one(self, filter_dict: Dict, update_dict: Dict) -> bool:
        """更新单个文档"""
        try:
            result = self.collection.update_one(filter_dict, update_dict)
            return result.modified_count > 0
        except Exception as e:
            current_app.logger.error(f"更新文档失败: {str(e)}")
            return False
    
    def delete_one(self, filter_dict: Dict) -> bool:
        """删除单个文档"""
        try:
            result = self.collection.delete_one(filter_dict)
            return result.deleted_count > 0
        except Exception as e:
            current_app.logger.error(f"删除文档失败: {str(e)}")
            return False
    
    def aggregate(self, pipeline: List[Dict]) -> List[Dict]:
        """聚合查询"""
        try:
            return list(self.collection.aggregate(pipeline))
        except Exception as e:
            current_app.logger.error(f"聚合查询失败: {str(e)}")
            return []
    
    def text_search(self, query: str, limit: int = 20) -> List[Dict]:
        """全文搜索"""
        try:
            return list(self.collection.find(
                {"$text": {"$search": query}},
                {"score": {"$meta": "textScore"}}
            ).sort([("score", {"$meta": "textScore"})]).limit(limit))
        except Exception as e:
            current_app.logger.error(f"全文搜索失败: {str(e)}")
            return []

def get_db_client():
    """获取MongoDB客户端实例"""
    global _db_client
    return _db_client


# 导出公共接口
__all__ = ['init_database', 'get_database_status', 'get_collection', 'get_database', 'close_database', 'DatabaseManager', 'get_db_client']